﻿using System;

namespace FreeSwitch.EventSocket.Parser
{
	public class StringBuffer
	{
		private char[] _buffer;
		private int _currentLength;
		private int _index;

		public StringBuffer(int capacity)
		{
			_buffer = new char[capacity];
		}

		/// <summary>
		/// Gets or sets description.
		/// </summary>
		public int Capacity
		{
			get { return _buffer.Length; }
		}

		/// <summary>
		/// Gets or sets if buffer can grow in size automatically.
		/// </summary>
		public bool AutoGrow { get; set; }

		public int Count
		{
			get { return _currentLength; }
		}

		public void Append(char[] buffer, int offset, int count)
		{
			if (_currentLength + count > Capacity)
			{
				if (!AutoGrow)
					throw new ArgumentOutOfRangeException(
						string.Format(
							"StringBuffer is too small (capacity: {0}, current size: {1}). Was requested to add additional {2} bytes.",
							Capacity, _currentLength, count));

				int newSize = Capacity*2;
				while (newSize < _currentLength + count)
					newSize = newSize*2;

				var newBuffer = new char[newSize];
				Array.Copy(_buffer, 0, newBuffer, 0, _currentLength);
				_buffer = newBuffer;
			}

			Array.Copy(buffer, 0, _buffer, _currentLength, count);
			_currentLength += count;
		}

		public void Append(char[] buffer)
		{
			Append(buffer, 0, buffer.Length);
		}

		public void Clear()
		{
			_currentLength = 0;
		}

		/// <summary>
		/// Copy chars from the StringBuffer into the specified array and remove them from the buffer.
		/// </summary>
		/// <param name="buffer">Buffer to pop bytes to</param>
		/// <param name="offset">Start offset in buffer</param>
		/// <param name="count">Number of characters to copy</param>
		public void Pop(char[] buffer, int offset, int count)
		{
			Array.Copy(_buffer, 0, buffer, offset, count);
			Array.Copy(_buffer, count, _buffer, 0, _currentLength - count);
			_currentLength -=  count;
		}


		public char Peek()
		{
			return _buffer[0];
		}

		public string ReadLine()
		{
			// empty line
			if (_buffer[0] == '\n')
			{
				Array.Copy(_buffer, 1, _buffer, 0, _currentLength - 1);
				_currentLength -= 1;
				return string.Empty;
			}

			int index = 0;
			while (_buffer[index] != '\r' && _buffer[index] != '\n')
				++index;

			var str = new string(_buffer, 0, index);

			int count = index; //since we do not want to copy vertical white spaces
			++index;
			if (_buffer[index + 1] == '\n') //for \r\n
				index++;
			Array.Copy(_buffer, index, _buffer, 0, _currentLength - count);
			_currentLength -= index;

			return str;
		}

		public void CopyTo(char[] value, int offset, int count)
		{
			Array.Copy(_buffer, 0, value, offset, count);
		}
	}
}